package com.sc.log;

import com.alibaba.fastjson.JSONObject;
import com.sc.common.annotations.OperationLog;
import com.sc.common.context.DefaultBusinessContext;
import com.sc.common.util.CommonUtil;
import com.sc.common.util.NetworkUtil;
import com.sc.mq.producer.Producer4routingKey;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by wust on 2019/5/27.
 */
@Aspect
@Order(1)
@Component
public class OperationLogAspect {
    @Autowired
   private Producer4routingKey producer4routingKey;

    @Value("${spring.rabbitmq.operationlog.exchange.name}")
    private String operationlogExchange;

    @Value("${spring.rabbitmq.operationlog.routing-key}")
    private String operationlogRoutingKey;


    @Before("execution(* com.sc..*(..)) && @annotation(com.sc.common.annotations.OperationLog)")
    public void before(JoinPoint jp) throws Throwable {
        Signature sig = jp.getSignature();
        if (sig instanceof MethodSignature) {
            MethodSignature methodSignature = (MethodSignature) sig;
            Method currentMethod = jp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());

            Object annotationObj = currentMethod.getAnnotation(OperationLog.class);
            if(annotationObj != null) {
                OperationLog operationLogAnnotation = (OperationLog) annotationObj;
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                DefaultBusinessContext ctx = DefaultBusinessContext.getContext();
                Object[] args = jp.getArgs();

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("moduleName",operationLogAnnotation.moduleName().getValue());
                jsonObject.put("businessName",operationLogAnnotation.businessName());
                jsonObject.put("operationType",operationLogAnnotation.operationType().getValue());
                jsonObject.put("operationIp",NetworkUtil.getIpAddress(request));
                jsonObject.put("operationData",parse2string(args));
                jsonObject.put("source",getServerName());
                jsonObject.put("createrId",ctx.getAccountId());
                jsonObject.put("createrName",ctx.getAccountName());
                jsonObject.put("createTime",new Date());

                String exchangeName = operationlogExchange;
                String routingKey = operationlogRoutingKey;
                producer4routingKey.send(exchangeName,routingKey,jsonObject);
            }
        }
    }


    private String getServerName() {
        PropertiesPropertySource propertiesPropertySource4applicationProperties = CommonUtil.getPropertiesPropertySource("applicationProperties");
        if(propertiesPropertySource4applicationProperties == null){
            return "none";
        }
        String applicationNameFromServer = propertiesPropertySource4applicationProperties.getProperty("spring.application.name").toString();
        return applicationNameFromServer;
    }

    private String parse2string(Object[] args){
        if(args != null && args.length > 0){
            List<Object> list = new ArrayList();
            for (Object arg : args) {
                if (arg instanceof ServletRequest){
                    continue;
                }
                list.add(arg);
            }
            if(list.size() > 0){
                return list.toString();
            }
        }
        return "";
    }
}
